<template>
  <div v-if="visible" class="floating-panel">
    <span class="close-btn" role="button" aria-label="关闭" tabindex="0" @click="handleCancel" @keydown.enter="handleCancel">×</span>
    <div class="floating-panel__header">位移边界</div>
    <div class="floating-panel__body">
      <el-form ref="formRef" :model="form" :rules="rules" label-width="80px" size="small" class="boundary-form">
        <el-form-item label="作用域" prop="setKey">
          <el-select v-model="form.setKey" placeholder="选择集合" filterable clearable style="width:240px">
            <el-option v-for="s in availableSets" :key="s.key" :label="s.name" :value="s.key" />
          </el-select>
        </el-form-item>
        <el-form-item label="自由度" prop="dofs">
          <el-checkbox-group v-model="form.dofs" class="dof-group">
            <el-checkbox v-for="d in dofOptions" :key="d" :label="d">{{ d }}</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" size="small" :disabled="!form.setKey || form.dofs.length===0" @click="handleConfirm">确认</el-button>
          <el-button size="small" @click="handleCancel">取消</el-button>
        </el-form-item>
      </el-form>
      <div v-if="availableSets.length===0" class="empty-hint">暂无可选集合</div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted, onBeforeUnmount, watch } from 'vue'
import type { ProjectTreeNode } from '@/store/modules/tree'
import { useTreeStore } from '@/store/modules/tree'
import { usePropertyForm } from '../composables/usePropertyForm'
import { useAvailableSets } from '../composables/useAvailableSets'

const props = defineProps<{ node?: ProjectTreeNode | null; projectId?: number | string | null }>()
const emit = defineEmits<{ (e:'cancel'):void; (e:'confirm'):void; (e:'update', v:any):void }>()

const visible = ref(true)
function handleCancel(){ visible.value=false; emit('cancel') }
function handleKey(e:KeyboardEvent){ if(e.key==='Escape'&&visible.value) handleCancel() }

// 表单
const form = reactive<{ setKey: string; dofs: string[] }>({ setKey: '', dofs: [] })
const rules = {
  setKey: [{ required: true, message: '请选择集合', trigger: 'change' }],
  dofs: [{ required: true, message: '至少选择一个自由度', trigger: 'change' }]
}
const dofOptions = ['UX','UY','UZ','RX','RY','RZ']

const treeStore = useTreeStore()
function ensureLoaded(){ if (props.projectId!=null && treeStore.getTree(props.projectId).length===0) treeStore.load(props.projectId) }

// 使用公共的 useAvailableSets 代替本地 availableSets 计算逻辑
const { availableSets } = useAvailableSets(computed(()=>props.projectId), 'setChildren');

const bridgeEmit = (e:'confirm'|'cancel') => { if(e==='confirm'){ emit('update',{ ...form }); emit('confirm') } else emit('cancel') }
const { formRef, handleConfirm } = usePropertyForm(form, { node: props.node, projectId: props.projectId, persist: false, namespace: 'displacementBoundary' }, bridgeEmit)

onMounted(()=>{ window.addEventListener('keydown',handleKey); ensureLoaded() })
onBeforeUnmount(()=>window.removeEventListener('keydown',handleKey))
watch(()=>props.projectId, ()=>ensureLoaded())
</script>
<style scoped lang="scss">
@use './common.scss' as *;
.boundary-form { display:flex; flex-direction:column; gap:8px; }
.empty-hint { font-size:12px; color:#999; margin-top:4px; }
.dof-group { display:flex; flex-wrap:wrap; gap:4px 12px; }
</style>